/*****************************************************************************
* Keppe Messenger (KMP) Keppe Project-Team User Messaging System
* Copyright (C) 2013-2014 Keppe Project-Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>.
*****************************************************************************/

#include <QObject>
#if QT_VERSION >= 0x050000
#ifdef WIN32
#define Q_WS_WIN
#endif
#endif

#include "KServerChat.h"
#include "ui_KServerChat.h"
#include <QMessageBox>
#include <QTcpSocket>
#include <QSettings>
#include <QProcess>
#include <QObject>
#include <QTimer>
#include <QMenu>
QMap<KServerChat*,QTcpSocket*> socket;
QMap<KServerChat*,QString> appver;
QMap<KServerChat*,QString> sysver;
QMap<KServerChat*,QString> sclast;
QMap<KServerChat*,QString> myuser;
QMap<KServerChat*,QString> mSerial;
//Tab
QMap<KServerChat*,QString> tabString;
QMap<KServerChat*,int> tabInt;
UnixName usysver;

KServerChat::KServerChat(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::KServerChat)
{
    ui->setupUi(this);
    ui->tbChat->setOpenAutoBrowser(true);
    appver[this] = "1.0.9.0-1";
    socket[this] = new QTcpSocket();
    sysver[this] = usysver.getUnixName();
    connect(socket[this],SIGNAL(readyRead()),this,SLOT(readyRead()));
    connect(socket[this],SIGNAL(disconnected()),this,SLOT(disconnected()));
    QTimer::singleShot(10,this,SLOT(automaticLength()));
    QTimer::singleShot(50,this,SLOT(checkReadyRead()));
}

KServerChat::~KServerChat()
{
    delete ui;
}

void KServerChat::checkReadyRead()
{
    while (socket[this]->canReadLine())
    {
        doSocket(socket[this]);
    }
    QTimer::singleShot(50,this,SLOT(checkReadyRead()));
}

void KServerChat::automaticLength()
{
    ui->txtMessageBox->setMinimumSize(ui->layout1->geometry().width(), 35);
    QTimer::singleShot(10,this,SLOT(automaticLength()));
}

void KServerChat::setSerial(QString serial)
{
    mSerial[this] = serial;
}

bool KServerChat::connectChat(QString serverIP, QString username)
{
    myuser[this] = username;
    socket[this]->connectToHost(serverIP,9501);
    if (socket[this]->waitForConnected(5000))
    {
        QByteArray header = QString("Version: ").toUtf8() + sysver[this].toUtf8() + QString("<>").toUtf8() + appver[this].toUtf8() + QString("<>Messenger\n").toUtf8() + username.toUtf8() + QString("\n").toUtf8() + mSerial[this].toUtf8() + QString("\n").toUtf8();
        socket[this]->write(header);
        socket[this]->flush();
        return true;
    }
    else
    {
        return false;
    }
}

void KServerChat::setTabID(int tabID)
{
    tabInt[this] = tabID;
}

int KServerChat::getTabID()
{
    return tabInt[this];
}

void KServerChat::setTabName(QString tabName)
{
    tabString[this] = tabName;
}

QString KServerChat::getTabName()
{
    return tabString[this];
}

void KServerChat::readyRead()
{
    QTcpSocket *server = (QTcpSocket*)sender();
    doSocket(server);
}

void KServerChat::disconnected()
{
    emit this->chatDisconnected();
}

bool KServerChat::isUserKnown(QString username)
{
    QSettings settings("Keppe","Keppe Messenger");
    settings.beginGroup("Nick");
    bool isKnown = settings.contains(username);
    settings.endGroup();
    return isKnown;
}

QString KServerChat::getCustomNick(QString username)
{
    QSettings settings("Keppe","Keppe Messenger");
    settings.beginGroup("Nick");
    QString normalNick;
    normalNick = settings.value(username, username).toString();
    settings.endGroup();
    settings.beginGroup("CustomNick");
    QString nickname = settings.value(username, normalNick).toString();
    settings.endGroup();
    if (nickname.trimmed() == "") {nickname = normalNick;}
    return nickname;
}

QString KServerChat::convertMessage(QString message)
{
    message = " " + message + " ";
    message = message.replace(QRegExp(" ((?:https?|ftp)://\\S+) "), " <a href=\"\\1\">\\1</a> ");
    message = message.replace(" :) "," <img src=':/img/friendly.png'/> ");
    message = message.replace(" :-) "," <img src=':/img/friendly.png'/> ");
    message = message.replace(" :| "," <img src=':/img/normal.png'/> ");
    message = message.replace(" :-| "," <img src=':/img/normal.png'/> ");
    message = message.replace(" :D "," <img src=':/img/laughting.png'/> ");
    message = message.replace(" :-D "," <img src=':/img/laughting.png'/> ");
    message = message.replace(" :P "," <img src=':/img/haha.png'/> ");
    message = message.replace(" :-P "," <img src=':/img/haha.png'/> ");
    message = message.replace(" :( "," <img src=':/img/sad.png'/> ");
    message = message.replace(" :-( "," <img src=':/img/sad.png'/> ");
    message = message.replace(" ;( "," <img src=':/img/cry.png'/> ");
    message = message.replace(" ;-( "," <img src=':/img/cry.png'/> ");
    message = message.replace(" (cry) "," <img src=':/img/cry.png'/> ");
    message = message.replace(" (angry) "," <img src=':/img/angry.png'/> ");
    message = message.replace(" (evil) "," <img src=':/img/evil.png'/> ");
    message = message.trimmed();
    return message;
}

void KServerChat::doSocket(QTcpSocket *server)
{
    QByteArray readed = server->readLine().trimmed();
    QString readstr = QString::fromUtf8(readed);
    if (readstr.left(5) == "ping " || readstr == "ping")
    {
        server->write("pong\n");
        server->flush();
    }
    if (readstr.left(4) == "say ")
    {
        readstr = readstr.remove(0,4);
        if (readstr.contains(": "))
        {
            QStringList readqsl = readstr.split(": ");
            QString username = readqsl.at(0);
            QString message = readstr.remove(0,username.length()+2);
            QString nickname = getCustomNick(username);
            bool isKnown = isUserKnown(username);
            if (username == "Server Version" || username == "Server")
            {
                if (!message.contains("The Server recommended Version is"))
                {
                    if (sclast[this] != username)
                    {
                        ui->tbChat->append("<span style=\"color: green\">" + username + "</span><br><span>" + convertMessage(message) + "</span>");
                    }
                    else
                    {
                        ui->tbChat->append("<span>" + convertMessage(message) + "</span>");
                    }
                    sclast[this] = username;
                }
            }
            else if (sclast[this] != username)
            {
                if (myuser[this] == username)
                {
                    ui->tbChat->append("<span style=\"color: grey\">" + nickname + "</span><br><span>" + convertMessage(message) + "</span>");
                }
                else if (isKnown)
                {
                    ui->tbChat->append("<span style=\"color: blue\">" + nickname + "</span><br><span>" + convertMessage(message) + "</span>");
                }
                else
                {
                    ui->tbChat->append("<span style=\"color: red\">" + nickname + "</span><br><span>" + convertMessage(message) + "</span>");
                }
                sclast[this] = username;
            }
            else
            {
                ui->tbChat->append("<span>" + convertMessage(message) + "</span>");
                sclast[this] = username;
            }
        }
    }
    if (readstr.left(4) == "csc ")
    {
        readstr = readstr.remove(0,4);
        if (readstr.contains(": "))
        {
            QStringList readqsl = readstr.split(": ");
            QString username = readqsl.at(0);
            QString message = readstr.remove(0,username.length()+2);
            if (username == "Server Version" || username == "Server")
            {
                if (!message.contains("The Server recommended Version is"))
                {
                    if (sclast[this] != QString("kcpq:" +  username))
                    {
                        ui->tbChat->append("<span style=\"color: green\">" + username + "</span><br><span>" + convertMessage(message) + "</span>");
                    }
                    else
                    {
                        ui->tbChat->append("<span>" + convertMessage(message) + "</span>");
                    }
                    sclast[this] = QString("kcpq:" +  username);
                }
            }
            else if (sclast[this] != QString("kcpq:" +  username))
            {
                ui->tbChat->append("<span style=\"color: #5E610B\">" + username + "</span><br><span>" + convertMessage(message) + "</span>");
                sclast[this] = QString("kcpq:" +  username);
            }
            else
            {
                ui->tbChat->append("<span>" + convertMessage(message) + "</span>");
                sclast[this] = QString("kcpq:" +  username);
            }
        }
    }
    if (readstr.left(4) == "csm ")
    {
        readstr = readstr.remove(0,4);
        if (readstr.contains(": "))
        {
            QStringList readqsl = readstr.split(": ");
            QString username = readqsl.at(0);
            QString message = readstr.remove(0,username.length()+2);
            QString nickname = getCustomNick(username);
            bool isKnown = isUserKnown(username);
            if (sclast[this] != username)
            {
                if (myuser[this] == username)
                {
                    ui->tbChat->append("<span style=\"color: grey\">" + nickname + "</span><br><span>" + convertMessage(message) + "</span>");
                }
                else if (isKnown)
                {
                    ui->tbChat->append("<span style=\"color: blue\">" + nickname + "</span><br><span>" + convertMessage(message) + "</span>");
                }
                else
                {
                    ui->tbChat->append("<span style=\"color: red\">" + nickname + "</span><br><span>" + convertMessage(message) + "</span>");
                }
                sclast[this] = username;
            }
            else
            {
                ui->tbChat->append("<span>" + convertMessage(message) + "</span>");
                sclast[this] = username;
            }
        }
    }
    if (readstr.left(4) == "scd ")
    {
        readstr = readstr.remove(0,4);
        QString username = readstr;
        if (sclast[this] != QString("kcpq: Server"))
        {
            ui->tbChat->append("<span style=\"color: green\">Server</span><br><span style=\"color: #5E610B\">" + username + "</span><span> has left the Server</span>");
        }
        else
        {
            ui->tbChat->append("<span style=\"color: #5E610B\">" + username + "</span><span> has left the Server</span>");;
        }
        sclast[this] = QString("kcpq: Server");
    }
    if (readstr.left(4) == "smd ")
    {
        readstr = readstr.remove(0,4);
        QString username = readstr;
        QString nickname = getCustomNick(username);
        bool isKnown = isUserKnown(username);
        if (sclast[this] != QString("kcpq: Server"))
        {
            if (isKnown)
            {
                ui->tbChat->append("<span style=\"color: green\">Server</span><br><span style=\"color: blue\">" + nickname + "</span><span> has left the Server</span>");
            }
            else
            {
                ui->tbChat->append("<span style=\"color: green\">Server</span><br><span style=\"color: red\">" + nickname + "</span><span> has left the Server</span>");
            }
        }
        else
        {
            if (isKnown)
            {
                ui->tbChat->append("<span style=\"color: blue\">" + nickname + "</span><span> has left the Server</span>");
            }
            else
            {
                ui->tbChat->append("<span style=\"color: red\">" + nickname + "</span><span> has left the Server</span>");
            }
        }
        sclast[this] = QString("kcpq: Server");
    }
    if (readstr.left(4) == "scb ")
    {
        readstr = readstr.remove(0,4);
        QString username = readstr;
        if (sclast[this] != QString("kcpq: Server"))
        {
            ui->tbChat->append("<span style=\"color: green\">Server</span><br><span style=\"color: #5E610B\">" + username + "</span><span> has been banned from this Server</span>");
        }
        else
        {
            ui->tbChat->append("<span style=\"color: #5E610B\">" + username + "</span><span> has been banned from this Server</span>");;
        }
        sclast[this] = QString("kcpq: Server");
    }
    if (readstr.left(4) == "smb ")
    {
        readstr = readstr.remove(0,4);
        QString username = readstr;
        QString nickname = getCustomNick(username);
        bool isKnown = isUserKnown(username);
        if (sclast[this] != QString("kcpq: Server"))
        {
            if (isKnown)
            {
                ui->tbChat->append("<span style=\"color: green\">Server</span><br><span style=\"color: blue\">" + nickname + "</span><span> has been banned from this Server</span>");
            }
            else
            {
                ui->tbChat->append("<span style=\"color: green\">Server</span><br><span style=\"color: red\">" + nickname + "</span><span> has been banned from this Server</span>");
            }
        }
        else
        {
            if (isKnown)
            {
                ui->tbChat->append("<span style=\"color: blue\">" + nickname + "</span><span> has been banned from this Server</span>");
            }
            else
            {
                ui->tbChat->append("<span style=\"color: red\">" + nickname + "</span><span> has been banned from this Server</span>");
            }
        }
        sclast[this] = QString("kcpq: Server");
    }
    if (readstr.left(4) == "sck ")
    {
        readstr = readstr.remove(0,4);
        QString username = readstr;
        if (sclast[this] != QString("kcpq: Server"))
        {
            ui->tbChat->append("<span style=\"color: green\">Server</span><br><span style=\"color: #5E610B\">" + username + "</span><span> has been kicked from this Server</span>");
        }
        else
        {
            ui->tbChat->append("<span style=\"color: #5E610B\">" + username + "</span><span> has been kicked from this Server</span>");;
        }
        sclast[this] = QString("kcpq: Server");
    }
    if (readstr.left(4) == "smk ")
    {
        readstr = readstr.remove(0,4);
        QString username = readstr;
        QString nickname = getCustomNick(username);
        bool isKnown = isUserKnown(username);
        if (sclast[this] != QString("kcpq: Server"))
        {
            if (isKnown)
            {
                ui->tbChat->append("<span style=\"color: green\">Server</span><br><span style=\"color: blue\">" + nickname + "</span><span> has been kicked from this Server</span>");
            }
            else
            {
                ui->tbChat->append("<span style=\"color: green\">Server</span><br><span style=\"color: red\">" + nickname + "</span><span> has been kicked from this Server</span>");
            }
        }
        else
        {
            if (isKnown)
            {
                ui->tbChat->append("<span style=\"color: blue\">" + nickname + "</span><span> has been kicked from this Server</span>");
            }
            else
            {
                ui->tbChat->append("<span style=\"color: red\">" + nickname + "</span><span> has been kicked from this Server</span>");
            }
        }
        sclast[this] = QString("kcpq: Server");
    }
    if (readstr.left(4) == "scc ")
    {
        readstr = readstr.remove(0,4);
        QString username = readstr;
        if (sclast[this] != QString("kcpq: Server"))
        {
            ui->tbChat->append("<span style=\"color: green\">Server</span><br><span style=\"color: #5E610B\">" + username + "</span><span> has joined the Chat</span>");
        }
        else
        {
            ui->tbChat->append("<span style=\"color: #5E610B\">" + username + "</span><span> has joined the Chat</span>");;
        }
        sclast[this] = QString("kcpq: Server");
    }
    if (readstr.left(4) == "scm ")
    {
        readstr = readstr.remove(0,4);
        QString username = readstr;
        QString nickname = getCustomNick(username);
        bool isKnown = isUserKnown(username);
        if (sclast[this] != QString("kcpq: Server"))
        {
            if (isKnown)
            {
                ui->tbChat->append("<span style=\"color: green\">Server</span><br><span style=\"color: blue\">" + nickname + "</span><span> has joined the Chat</span>");
            }
            else
            {
                ui->tbChat->append("<span style=\"color: green\">Server</span><br><span style=\"color: red\">" + nickname + "</span><span> has joined the Chat</span>");
            }
        }
        else
        {
            if (isKnown)
            {
                ui->tbChat->append("<span style=\"color: blue\">" + nickname + "</span><span> has joined the Chat</span>");
            }
            else
            {
                ui->tbChat->append("<span style=\"color: red\">" + nickname + "</span><span> has joined the Chat</span>");
            }
        }
        sclast[this] = QString("kcpq: Server");
    }
}

void KServerChat::on_cmdDisconnect_clicked()
{
    socket[this]->disconnectFromHost();
}

void KServerChat::disconnectChat()
{
    socket[this]->disconnectFromHost();
}

void KServerChat::on_txtMessageBox_returnPressed()
{
    sendMessage();
}

void KServerChat::sendMessage()
{
    QString text = QString::fromUtf8(ui->txtMessageBox->text().toUtf8());
    text.replace(QString::fromUtf8("&"),"&amp;");
    text.replace(QString::fromUtf8("<"),"&lt;");
    text.replace(QString::fromUtf8(">"),"&gt;");
    text.replace(QString::fromUtf8("\""),"&quot;");
    text.replace(QString::fromUtf8("ä"),"&auml;");
    text.replace(QString::fromUtf8("ö"),"&ouml;");
    text.replace(QString::fromUtf8("ü"),"&uuml;");
    text.replace(QString::fromUtf8("Ä"),"&Auml;");
    text.replace(QString::fromUtf8("Ö"),"&Ouml;");
    text.replace(QString::fromUtf8("Ü"),"&Uuml;");
    text.replace(QString::fromUtf8("ß"),"&szlig;");
    text.replace(QString::fromUtf8("€"),"&euro;");
    text.replace(QString::fromUtf8("§"),"&sect;");
    text.replace(QString::fromUtf8("©"),"&copy;");
    text.replace(QString::fromUtf8("®"),"&reg;");
    text.replace(QString::fromUtf8("°"),"&deg;");
    text.replace(QString::fromUtf8("²"),"&sup2;");
    text.replace(QString::fromUtf8("³"),"&sup3;");
    text.replace(QString::fromUtf8("\r\n"),"<br>");
    text.replace(QString::fromUtf8("\r"),"<br>");
    text.replace(QString::fromUtf8("\n"),"<br>");
    if (text.trimmed() == QString("")) return;
    socket[this]->write("say " + text.toUtf8() + "\n");
    ui->txtMessageBox->clear();
}

void KServerChat::on_cmdSmiley_clicked()
{
    QMenu *smileyContext = new QMenu();
    QAction *evilSmiley = smileyContext->addAction(QIcon(":/img/evil.png"),"(evil)");
    connect(evilSmiley,SIGNAL(triggered()),this,SLOT(addEvilSmiley()));
    QAction *friendlySmiley = smileyContext->addAction(QIcon(":/img/friendly.png"),":)");
    connect(friendlySmiley,SIGNAL(triggered()),this,SLOT(addFriendlySmiley()));
    QAction *laughtingSmiley = smileyContext->addAction(QIcon(":/img/laughting.png"),":D");
    connect(laughtingSmiley,SIGNAL(triggered()),this,SLOT(addLaughtingSmiley()));
    QAction *hahaSmiley = smileyContext->addAction(QIcon(":/img/haha.png"),":P");
    connect(hahaSmiley,SIGNAL(triggered()),this,SLOT(addHahaSmiley()));
    QAction *normalSmiley = smileyContext->addAction(QIcon(":/img/normal.png"),":|");
    connect(normalSmiley,SIGNAL(triggered()),this,SLOT(addNormalSmiley()));
    QAction *sadSmiley = smileyContext->addAction(QIcon(":/img/sad.png"),":(");
    connect(sadSmiley,SIGNAL(triggered()),this,SLOT(addSadSmiley()));
    QAction *angrySmiley = smileyContext->addAction(QIcon(":/img/angry.png"),"(angry)");
    connect(angrySmiley,SIGNAL(triggered()),this,SLOT(addAngrySmiley()));
    QAction *crySmiley = smileyContext->addAction(QIcon(":/img/cry.png"),"(cry)");
    connect(crySmiley,SIGNAL(triggered()),this,SLOT(addCrySmiley()));
    smileyContext->popup(QCursor::pos());
}

void KServerChat::appendTextToLineEdit(QLineEdit *lineedit, QString text)
{
    QString ntext = lineedit->text();
    ntext = ntext + text;
    lineedit->setText(ntext);
    lineedit->setFocus();
}

void KServerChat::addEvilSmiley()
{
    appendTextToLineEdit(ui->txtMessageBox," (evil) ");
}

void KServerChat::addFriendlySmiley()
{
    appendTextToLineEdit(ui->txtMessageBox," :) ");
}

void KServerChat::addLaughtingSmiley()
{
    appendTextToLineEdit(ui->txtMessageBox," :D ");
}

void KServerChat::addHahaSmiley()
{
    appendTextToLineEdit(ui->txtMessageBox," :P ");
}

void KServerChat::addNormalSmiley()
{
    appendTextToLineEdit(ui->txtMessageBox," :| ");
}

void KServerChat::addSadSmiley()
{
    appendTextToLineEdit(ui->txtMessageBox," :( ");
}

void KServerChat::addAngrySmiley()
{
    appendTextToLineEdit(ui->txtMessageBox," (angry) ");
}

void KServerChat::addCrySmiley()
{
    appendTextToLineEdit(ui->txtMessageBox," (cry) ");
}

void KServerChat::on_cmdSend_clicked()
{
    on_txtMessageBox_returnPressed();
    ui->txtMessageBox->setFocus();
}

QString UnixName::getUnixName()
{
#if defined(Q_WS_LINUX)
    QProcess unamep;
    QStringList unamea;
    unamea.append("-v");
    unamep.start("uname",unamea);
    if (!unamep.waitForStarted()) return "Linux";
    if (unamep.waitForFinished())
    {
        QByteArray unamer = unamep.readAll();
        if (unamer.contains("Ubuntu")) return "Ubuntu";
        else if (unamer.contains("Debian")) return "Debian";
        else if (unamer.contains("Keppe OS")) return "Keppe OS";
        else return "Linux";
    }
#elif defined(Q_WS_X11)
    QProcess unamep;
    QStringList unamea;
    unamea.append("-v");
    unamep.start("uname",unamea);
    if (!unamep.waitForStarted()) return "Unix";
    if (unamep.waitForFinished())
    {
        QByteArray unamer = unamep.readAll();
        if (unamer.contains("Ubuntu")) return "Ubuntu";
        else if (unamer.contains("Debian")) return "Debian";
        else if (unamer.contains("Keppe OS")) return "Keppe OS";
        else return "Unix";
    }
#endif
    return getWindowsName(true);
}

QString UnixName::getWindowsName(bool triggered=false)
{
#if defined(Q_WS_WIN64)
    if (QSysInfo::windowsVersion() == QSysInfo::WV_4_0) return "Windows NT 4.0 x64";
    if (QSysInfo::windowsVersion() == QSysInfo::WV_5_0) return "Windows 2000 x64";
    if (QSysInfo::windowsVersion() == QSysInfo::WV_5_1) return "Windows XP x64";
    if (QSysInfo::windowsVersion() == QSysInfo::WV_5_2) return "Windows XP x64";
    if (QSysInfo::windowsVersion() == QSysInfo::WV_6_0) return "Windows Vista x64";
    if (QSysInfo::windowsVersion() == QSysInfo::WV_6_1) return "Windows 7 x64";
    if (QSysInfo::windowsVersion() == 0x00a0) return "Windows 8 x64";
    if (QSysInfo::windowsVersion() == 0x00b0) return "Windows 8.1 x64";
    return "Windows x64";
#elif defined(Q_WS_WIN)
    if (QSysInfo::windowsVersion() == QSysInfo::WV_4_0) return "Windows NT 4.0";
    if (QSysInfo::windowsVersion() == QSysInfo::WV_5_0) return "Windows 2000";
    if (QSysInfo::windowsVersion() == QSysInfo::WV_5_1) return "Windows XP";
    if (QSysInfo::windowsVersion() == QSysInfo::WV_5_2) return "Windows XP";
    if (QSysInfo::windowsVersion() == QSysInfo::WV_6_0) return "Windows Vista";
    if (QSysInfo::windowsVersion() == QSysInfo::WV_6_1) return "Windows 7";
    if (QSysInfo::windowsVersion() == 0x00a0) return "Windows 8";
    if (QSysInfo::windowsVersion() == 0x00b0) return "Windows 8.1";
    return "Windows";
#endif
    if (!triggered)
    {
        return getUnixName();
    }
    return "Not detected";
}

UnixName::UnixName()
{
}
